# -*- coding: utf-8 -*-
#	Copyright 2005,2006,2007,2008 Spike^ekipS <spikeekips@gmail.com>
#
#	   This program is free software; you can redistribute it and/or modify
#	it under the terms of the GNU General Public License as published by
#	the Free Software Foundation; either version 2 of the License, or
#	(at your option) any later version.
#
#	This program is distributed in the hope that it will be useful,
#	but WITHOUT ANY WARRANTY; without even the implied warranty of
#	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#	GNU General Public License for more details.
#
#	You should have received a copy of the GNU General Public License
#	along with this program; if not, write to the Free Software
#	Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

from django.db.models.sql.where import WhereNode
from django.db import models, connection
from django.utils import tree
from django.db.models.sql.datastructures import EmptyResultSet, FullResultSet
from django.db.models.query_utils import QueryWrapper

import core
from pylucene import BooleanQuery, QUERY_BOOLEANS, TermQuery

import lucene

class WhereNodeSearcher (WhereNode) :

	query = None
	def as_sql(self, node=None, qn=None) :
		if self.query is None :
			self.query = BooleanQuery()

		if node is None:
			node = self

		if not qn:
			qn = connection.ops.quote_name
		if not node.children:
			return None

		empty = True
		for child in node.children:
			try:
				if hasattr(child, "as_sql") :
					sql = child.as_sql(qn=qn)
				elif isinstance(child, tree.Node) :
					sql = self.as_sql(child, qn)
				else:
					sql = self.make_atom(child, qn)
			except EmptyResultSet, e :
				if node.connector == AND and not node.negated:
					# We can bail out early in this particular case (only).
					raise
				elif node.negated:
					empty = False
				continue
			except FullResultSet:
				if self.connector == OR:
					if node.negated:
						empty = True
						break
					# We match everything. No need for any constraints.
					return None
				if node.negated:
					empty = True
				continue
			except Exception, e :
				raise

			empty = False
			if sql:
				if sql == self.query :
					return
				self.query.add(sql, QUERY_BOOLEANS.get(node.negated))
		if empty:
			raise EmptyResultSet

		return self.query

	def get_query (self) :
		return query

	def get_term (self, field, value) :
		return lucene.Term(field, value)

	def make_atom (self, child, qn) :
		table_alias, name, field, lookup_type, value = child
		try :
			value = core.DocumentValue.to_index(core.Model.get_field_type(field), value, flatten=True, )
		except Exception, e :
			print e
			raise

		subquery = None
		if lookup_type in connection.operators:
			if lookup_type in ("search", "contains", "icontains", ) :
				subquery = lucene.RegexQuery(
					self.get_term(
						field.name,
						"^.*%s.*$" % (lookup_type == "icontains" and value.lower() or value),
					)
				)
			elif lookup_type in ("regex", "iregex", ) :
				subquery = lucene.RegexQuery(
					self.get_term(
						field.name,
						lookup_type == "iregex" and value.lower() or value
					)
				)
			elif lookup_type in ("startswith", "istartswith", ) :
				subquery = lucene.RegexQuery(
					self.get_term(
						field.name,
						"^%s" % (lookup_type == "istartswith" and value.lower() or value),
					)
				)
			elif lookup_type in ("endswith", "iendswith", ) :
				subquery = lucene.RegexQuery(
					self.get_term(
						field.name,
						"%s$" % (lookup_type == "iendswith" and value.lower() or value),
					)
				)
			elif lookup_type in ("lt", "lte", ) :
				subquery = lucene.RangeQuery(
					None,
					self.get_term(field.name, value),
					False,
				)
			elif lookup_type in ("gt", "gte", ) :
				subquery = lucene.RangeQuery(
					self.get_term(field.name, value),
					None,
					False,
				)
			else :
				pass

		if lookup_type in ("exact", "iexact", ) :
			value = lookup_type == "iexact" and value.lower() or value
			subquery = TermQuery()
			for i in value.split() :
				subquery.add(self.get_term(field.name, i))
		elif lookup_type == "in" :
			subquery = BooleanQuery()
			for v in value :
				subquery.add(
					TermQuery(self.get_term(field.name, v)),
					QUERY_BOOLEANS.get("OR"),
				)
		elif lookup_type == "range" :
			value.sort()

			subquery = lucene.RangeQuery(
				self.get_term(field.name, value[0]),
				self.get_term(field.name, value[1]),
				False,
			)
		elif lookup_type == "year" :
			subquery = lucene.RegexQuery(
				self.get_term(field.name, "^%s" % value),
			)
		elif lookup_type in ("month", "day") :
			value = "%02d" % int(value)
			subquery = lucene.RegexQuery(
				self.get_term(field.name, "^[\d]{4}[\d]{2}%s" % value),
			)
		elif lookup_type == "isnull":
			subquery = lucene.RegexQuery(
				self.get_term(field.name, "^$")
			)
		if subquery :
			return subquery

		raise TypeError("Invalid lookup_type: %r" % lookup_type)


		return subquery

	def negate (self) :
		from django.utils.tree import Node
		self.children = [Node(self.children, self.connector, not self.negated)]
		self.connector = self.default



"""
Description
-----------


ChangeLog
---------


Usage
-----


"""

__author__ =  "Spike^ekipS <spikeekips@gmail.com>"




